package com.morty.pdf.pdf;

import com.morty.pdf.freemaker.HtmlGenerator;
import com.morty.pdf.pdf.exception.DocumentGeneratingException;
import com.morty.pdf.pdf.factory.ITextRendererObjectFactory;
import lombok.extern.log4j.Log4j2;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.nio.charset.Charset;

/**
 * pdf 生成
 *
 * @ClassName: PdfGenerator
 * @Description:pdf 生成
 * @author
 */
@Log4j2
public class PdfDocumentGenerator {

	private final static HtmlGenerator htmlGenerator;
	static {
		htmlGenerator = new HtmlGenerator();
	}

	/**
	 * 使用模板,模板数据,生成pdf
	 *
	 * @Title: generate
	 * @Description: 使用模板,模板数据,生成pdf
	 * @param template
	 *            classpath中路径模板路径
	 * @param documentVo
	 *            模板数据
	 * @param outputFile
	 *            生成pdf的路径
	 * @author
	 * @throws DocumentGeneratingException
	 */
	public boolean generate(String template, DocumentVo documentVo,
							String outputFile) throws DocumentGeneratingException {

		try {
			String htmlContent = htmlGenerator.generate(template, documentVo);
			System.out.println("ftl template : " + htmlContent);
			this.generate(htmlContent, outputFile);

			log.info("The document [primarykey="
					+ documentVo.findPrimaryKey()
					+ "] is generated successfully,and stored in ["
					+ outputFile + "]");

		} catch (Exception e) {
			String error = "The document [primarykey="
					+ documentVo.findPrimaryKey() + "] is failed to generate";
			log.error(error);
			throw new DocumentGeneratingException(error, e);
		}

		return true;
	}

	public ByteArrayOutputStream generate(String template, DocumentVo documentVo
	) throws DocumentGeneratingException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
//			BufferedReader in = new BufferedReader(
//					new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream(template)));
//
//			log.info(this.getClass().getClassLoader().getResourceAsStream(template));
//
//			StringBuilder buffer = new StringBuilder();
//			String line;
//			while ((line = in.readLine()) != null)
//			{
//				buffer.append(line);
//			}
//			String htmlContent = buffer.toString();
//
//			log.info(htmlContent);

			String htmlContent = htmlGenerator.generate(template, documentVo);
			out = this.generate(htmlContent);

			log.info("The document [primarykey="
					+ documentVo.findPrimaryKey()
					+ "] is generated successfully");

		} catch (Exception e) {
			String error = "The document [primarykey="
					+ documentVo.findPrimaryKey() + "] is failed to generate";
			log.error(error);
			throw new DocumentGeneratingException(error, e);
		}

		return out;
	}

	/**
	 * Output a pdf to the specified outputstream
	 *
	 * @param htmlContent
	 *            the htmlstr
	 * @param outputFile
	 *            the specified output file
	 * @throws Exception
	 */
	public void generate(String htmlContent, String outputFile)
			throws Exception {
		OutputStream out = null;
		ITextRenderer iTextRenderer = null;

		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			Document doc = builder.parse(new ByteArrayInputStream(htmlContent
					.getBytes(Charset.forName("utf-8"))));
			File f = new File(outputFile);
			if (f != null && !f.getParentFile().exists()) {
				f.getParentFile().mkdir();
			}
			out = new FileOutputStream(outputFile);

			iTextRenderer = (ITextRenderer) ITextRendererObjectFactory
					.getObjectPool().borrowObject();//获取对象池中对象

			try {
				iTextRenderer.setDocument(doc, null);
				iTextRenderer.layout();
				iTextRenderer.createPDF(out);
			} catch (Exception e) {
				ITextRendererObjectFactory.getObjectPool().invalidateObject(
						iTextRenderer);
				iTextRenderer = null;
				throw e;
			}

		} catch (Exception e) {
			throw e;
		} finally {
			if (out != null) {
				out.close();
			}

			if (iTextRenderer != null) {
				try {
					ITextRendererObjectFactory.getObjectPool().returnObject(
							iTextRenderer);
				} catch (Exception ex) {
					log.error("Cannot return object from pool.", ex);
				}
			}
		}
	}

	public ByteArrayOutputStream generate(String htmlContent)
			throws Exception {
//		OutputStream out = null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ITextRenderer iTextRenderer = null;

		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			Document doc = builder.parse(new ByteArrayInputStream(htmlContent
					.getBytes(Charset.forName("utf-8"))));
//			File f = new File();


			iTextRenderer = (ITextRenderer) ITextRendererObjectFactory
					.getObjectPool().borrowObject();//获取对象池中对象

			try {
				iTextRenderer.setDocument(doc, null);
				iTextRenderer.layout();
				iTextRenderer.createPDF(out);
			} catch (Exception e) {
				ITextRendererObjectFactory.getObjectPool().invalidateObject(
						iTextRenderer);
				iTextRenderer = null;
				throw e;
			}

		} catch (Exception e) {
			throw e;
		} finally {
			if (out != null) {
				out.close();
			}

			if (iTextRenderer != null) {
				try {
					ITextRendererObjectFactory.getObjectPool().returnObject(
							iTextRenderer);
				} catch (Exception ex) {
					log.error("Cannot return object from pool.", ex);
				}
			}
			return out;
		}
	}

}